﻿using System;
using System.Linq;
using _5E.Infrastructure.Logging;
using _5E.Infrastructure.Querying;
using _5E.Infrastructure.UnitOfWork;
using StoneAge.Contract;
using StoneAge.DataContract.Messaging;
using StoneAge.Models.Entity;
using StoneAge.Models.Enums;
using StoneAge.Models.Repository;
using StructureMap;

namespace StoneAge.Service
{
    public class RoleService : IRoleService
    {
        private static Coordinate[] s_birthCoordinates = null;
        private IRoleRepository m_roleRepository = null;
        private IUnitOfWork m_uow = null;
        private ILevelRepository m_levelRepository = null;

        static RoleService()
        {
            s_birthCoordinates = new Coordinate[]
            {
                GetCoordinateBy(4006, 14, 20)
            };
        }

        public RoleService(IRoleRepository roleRepository, IUnitOfWork uow, ILevelRepository levelRepository)
        {
            m_roleRepository = roleRepository;
            m_uow = uow;
            m_levelRepository = levelRepository;
        }

        private static Coordinate GetCoordinateBy(Int32 mapId, Int32 east, Int32 south)
        {
            ICoordinateRepository coordinateRepository = ObjectFactory.GetInstance<ICoordinateRepository>();
            Query query = new Query();
            query.Add<Coordinate>(c => c.MapId, CriteriaOperator.Eq, mapId);
            query.Add<Coordinate>(c => c.E, CriteriaOperator.Eq, east);
            query.Add<Coordinate>(c => c.S, CriteriaOperator.Eq, south);
            return coordinateRepository.FindBy(query).First();
        }

        public CreateRoleResponse CreateBy(CreateRoleRequest request)
        {
            CreateRoleResponse response = new CreateRoleResponse();
            Role role = request.Role;
            if (0 < role.BrokenRules.Count() && Array.Exists(s_birthCoordinates, c => c.MapId == request.BirthMapId))
            {
                try
                {
                    role.Id = Guid.NewGuid();
                    role.LoginCount = 1;
                    role.Dp = 100;
                    role.Charm = 60;
                    role.MaxBlood = role.Blood = role.Vit * 4 + role.Str + role.Sta + role.Agi;
                    role.MaxMana = role.Mana = 100;
                    role.Atk = role.Str + role.Sta / 10 + role.Agi / 10;
                    role.Def = role.Sta + role.Str / 10 + role.Agi / 10;
                    role.Speed = role.Agi;
                    role.Level = m_levelRepository.FindBy(1);
                    role.DirectionId = Convert.ToInt32(Direction.South);
                    role.Coordinate = Array.Find(s_birthCoordinates, c => c.MapId == request.BirthMapId);
                    m_roleRepository.Save(role);
                    m_uow.Comit();

                    response.RoleId = role.Id;
                }
                catch (Exception ex)
                {
                    LoggingFactory.Logger.Log(ex);
                    response.Success = false;
                }
            }
            else
            {
                response.Success = false;
            }
            return response;
        }

        public ChooseRoleResponse ChooseBy(ChooseRoleRequest request)
        {
            ChooseRoleResponse response = new ChooseRoleResponse();
            try
            {
                Query query = new Query();
                query.Add<Role>(r => r.AccountId, CriteriaOperator.Eq, request.AccountId);
                query.Add<Role>(r => r.IsLeft, CriteriaOperator.Eq, request.IsLeft);

                var roles = m_roleRepository.FindBy(query);
                if (0 < roles.Count())
                    response.RoleId = roles.First().Id;
            }
            catch (Exception ex)
            {
                LoggingFactory.Logger.Log(ex);
                response.Success = false;
            }
            return response;
        }
    }
}
